home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / aptsources / distinfo.py < prev    next >
Encoding:
Python Source  |  2009-03-30  |  9.8 KB  |  289 lines

  1. #!/usr/bin/env python
  2. #
  3. #  distinfo.py - provide meta information for distro repositories
  4. #
  5. #  Copyright (c) 2005 Gustavo Noronha Silva
  6. #                2006-2007 Sebastian Heinlein
  7. #
  8. #  Author: Gustavo Noronha Silva <kov@debian.org>
  9. #          Sebastian Heinlein <glatzor@ubuntu.com>
  10. #
  11. #  This program is free software; you can redistribute it and/or
  12. #  modify it under the terms of the GNU General Public License as
  13. #  published by the Free Software Foundation; either version 2 of the
  14. #  License, or (at your option) any later version.
  15. #
  16. #  This program is distributed in the hope that it will be useful,
  17. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. #  GNU General Public License for more details.
  20. #
  21. #  You should have received a copy of the GNU General Public License
  22. #  along with this program; if not, write to the Free Software
  23. #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  24. #  USA
  25.  
  26. import os
  27. import gettext
  28. from os import getenv
  29. import ConfigParser
  30. import re
  31.  
  32. import apt_pkg
  33.  
  34.  
  35. def _(s):
  36.     return gettext.dgettext("python-apt", s)
  37.  
  38.  
  39. class Template:
  40.  
  41.     def __init__(self):
  42.         self.name = None
  43.         self.child = False
  44.         self.parents = []          # ref to parent template(s)
  45.         self.match_name = None
  46.         self.description = None
  47.         self.base_uri = None
  48.         self.type = None
  49.         self.components = []
  50.         self.children = []
  51.         self.match_uri = None
  52.         self.mirror_set = {}
  53.         self.distribution = None
  54.         self.available = True
  55.  
  56.     def has_component(self, comp):
  57.         ''' Check if the distribution provides the given component '''
  58.         return comp in map(lambda c: c.name, self.components)
  59.  
  60.     def is_mirror(self, url):
  61.         ''' Check if a given url of a repository is a valid mirror '''
  62.         proto, hostname, dir = split_url(url)
  63.         if hostname in self.mirror_set:
  64.             return self.mirror_set[hostname].has_repository(proto, dir)
  65.         else:
  66.             return False
  67.  
  68.  
  69. class Component:
  70.  
  71.     def __init__(self, name, desc=None, long_desc=None):
  72.         self.name = name
  73.         self.description = desc
  74.         self.description_long = long_desc
  75.  
  76.     def get_description(self):
  77.         if self.description_long is not None:
  78.             return self.description_long
  79.         elif self.description is not None:
  80.             return self.description
  81.         else:
  82.             return None
  83.  
  84.     def set_description(self, desc):
  85.         self.description = desc
  86.  
  87.     def set_description_long(self, desc):
  88.         self.description_long = desc
  89.  
  90.     def get_description_long(self):
  91.         return self.description_long
  92.  
  93.  
  94. class Mirror:
  95.     ''' Storage for mirror related information '''
  96.  
  97.     def __init__(self, proto, hostname, dir, location=None):
  98.         self.hostname = hostname
  99.         self.repositories = []
  100.         self.add_repository(proto, dir)
  101.         self.location = location
  102.  
  103.     def add_repository(self, proto, dir):
  104.         self.repositories.append(Repository(proto, dir))
  105.  
  106.     def get_repositories_for_proto(self, proto):
  107.         return filter(lambda r: r.proto == proto, self.repositories)
  108.  
  109.     def has_repository(self, proto, dir):
  110.         if dir is None:
  111.             return False
  112.         for r in self.repositories:
  113.             if r.proto == proto and dir in r.dir:
  114.                 return True
  115.         return False
  116.  
  117.     def get_repo_urls(self):
  118.         return map(lambda r: r.get_url(self.hostname), self.repositories)
  119.  
  120.     def get_location(self):
  121.         return self.location
  122.  
  123.     def set_location(self, location):
  124.         self.location = location
  125.  
  126.  
  127. class Repository:
  128.  
  129.     def __init__(self, proto, dir):
  130.         self.proto = proto
  131.         self.dir = dir
  132.  
  133.     def get_info(self):
  134.         return self.proto, self.dir
  135.  
  136.     def get_url(self, hostname):
  137.         return "%s://%s/%s" % (self.proto, hostname, self.dir)
  138.  
  139.  
  140. def split_url(url):
  141.     ''' split a given URL into the protocoll, the hostname and the dir part '''
  142.     return map(lambda a, b: a, re.split(":*\/+", url, maxsplit=2),
  143.                [None, None, None])
  144.  
  145.  
  146. class DistInfo:
  147.  
  148.     def __init__(self,
  149.                  dist = None,
  150.                  base_dir = "/usr/share/python-apt/templates"):
  151.         self.metarelease_uri = ''
  152.         self.templates = []
  153.         self.arch = apt_pkg.Config.Find("APT::Architecture")
  154.  
  155.         location = None
  156.         match_loc = re.compile(r"^#LOC:(.+)$")
  157.         match_mirror_line = re.compile(
  158.             r"^(#LOC:.+)|(((http)|(ftp)|(rsync)|(file)|(https))://"
  159.             r"[A-Za-z0-9/\.:\-_@]+)$")
  160.         #match_mirror_line = re.compile(r".+")
  161.  
  162.         if not dist:
  163.             pipe = os.popen("lsb_release -i -s")
  164.             dist = pipe.read().strip()
  165.             pipe.close()
  166.             del pipe
  167.  
  168.         self.dist = dist
  169.  
  170.         map_mirror_sets = {}
  171.  
  172.         dist_fname = "%s/%s.info" % (base_dir, dist)
  173.         dist_file = open(dist_fname)
  174.         if not dist_file:
  175.             return
  176.         template = None
  177.         component = None
  178.         for line in dist_file:
  179.             tokens = line.split(':', 1)
  180.             if len(tokens) < 2:
  181.                 continue
  182.             field = tokens[0].strip()
  183.             value = tokens[1].strip()
  184.             if field == 'ChangelogURI':
  185.                 self.changelogs_uri = _(value)
  186.             elif field == 'MetaReleaseURI':
  187.                 self.metarelease_uri = value
  188.             elif field == 'Suite':
  189.                 self.finish_template(template, component)
  190.                 component=None
  191.                 template = Template()
  192.                 template.name = value
  193.                 template.distribution = dist
  194.                 template.match_name = "^%s$" % value
  195.             elif field == 'MatchName':
  196.                 template.match_name = value
  197.             elif field == 'ParentSuite':
  198.                 template.child = True
  199.                 for nanny in self.templates:
  200.                     # look for parent and add back ref to it
  201.                     if nanny.name == value:
  202.                         template.parents.append(nanny)
  203.                         nanny.children.append(template)
  204.             elif field == 'Available':
  205.                 template.available = value
  206.             elif field == 'RepositoryType':
  207.                 template.type = value
  208.             elif field == 'BaseURI' and not template.base_uri:
  209.                 template.base_uri = value
  210.             elif field == 'BaseURI-%s' % self.arch:
  211.                 template.base_uri = value
  212.             elif field == 'MatchURI' and not template.match_uri:
  213.                 template.match_uri = value
  214.             elif field == 'MatchURI-%s' % self.arch:
  215.                 template.match_uri = value
  216.             elif (field == 'MirrorsFile' or
  217.                   field == 'MirrorsFile-%s' % self.arch):
  218.                 if value not in map_mirror_sets:
  219.                     mirror_set = {}
  220.                     try:
  221.                         mirror_data = filter(match_mirror_line.match,
  222.                                              [x.strip() for x in open(value)])
  223.                     except Exception:
  224.                         print "WARNING: Failed to read mirror file"
  225.                         mirror_data = []
  226.                     for line in mirror_data:
  227.                         if line.startswith("#LOC:"):
  228.                             location = match_loc.sub(r"\1", line)
  229.                             continue
  230.                         (proto, hostname, dir) = split_url(line)
  231.                         if hostname in mirror_set:
  232.                             mirror_set[hostname].add_repository(proto, dir)
  233.                         else:
  234.                             mirror_set[hostname] = Mirror(
  235.                                 proto, hostname, dir, location)
  236.                     map_mirror_sets[value] = mirror_set
  237.                 template.mirror_set = map_mirror_sets[value]
  238.             elif field == 'Description':
  239.                 template.description = _(value)
  240.             elif field == 'Component':
  241.                 if component and not template.has_component(component.name):
  242.                     template.components.append(component)
  243.                 component = Component(value)
  244.             elif field == 'CompDescription':
  245.                 component.set_description(_(value))
  246.             elif field == 'CompDescriptionLong':
  247.                 component.set_description_long(_(value))
  248.         self.finish_template(template, component)
  249.         template=None
  250.         component=None
  251.  
  252.     def finish_template(self, template, component):
  253.         " finish the current tempalte "
  254.         if not template:
  255.             return
  256.         # reuse some properties of the parent template
  257.         if template.match_uri is None and template.child:
  258.             for t in template.parents:
  259.                 if t.match_uri:
  260.                     template.match_uri = t.match_uri
  261.                     break
  262.         if template.mirror_set == {} and template.child:
  263.             for t in template.parents:
  264.                 if t.match_uri:
  265.                     template.mirror_set = t.mirror_set
  266.                     break
  267.         if component and not template.has_component(component.name):
  268.             template.components.append(component)
  269.             component = None
  270.         self.templates.append(template)
  271.  
  272.  
  273. if __name__ == "__main__":
  274.     d = DistInfo("Ubuntu", "/usr/share/python-apt/templates")
  275.     print d.changelogs_uri
  276.     for template in d.templates:
  277.         print "\nSuite: %s" % template.name
  278.         print "Desc: %s" % template.description
  279.         print "BaseURI: %s" % template.base_uri
  280.         print "MatchURI: %s" % template.match_uri
  281.         if template.mirror_set != {}:
  282.             print "Mirrors: %s" % template.mirror_set.keys()
  283.         for comp in template.components:
  284.             print " %s -%s -%s" % (comp.name,
  285.                                    comp.description,
  286.                                    comp.description_long)
  287.         for child in template.children:
  288.             print "  %s" % child.description
  289.